#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
//代码运行正常
//void func(){
//    printf("用exit()退出");
//    exit(22);
//}
//
//
//int main(){
//    func();
//    printf("进程退出码测试");
//    return 11;
//}

//代码运行异常
//int main(){
//    int a = 1;
//    int b = a/0;
//    //此时程序的返回值不再是0，是当程序由于除以零而异常终止时，Linux 会为该进程分配一个退出状态码，通常遵循以下规则：
//    //信号导致的终止：如果程序因接收到某个信号而终止，退出状态码的计算方式为 128 + 信号编号。 对于 浮点异常（FPE），对应的信号编号是 8（SIGFPE）。因此，退出状态码为：
//    //128 + 8 = 136
//    //然而，实际中更常见的是 FPE_INTDIV（整数除以零），其信号编号仍然是 8，所以退出状态码通常为 136
//    return 0;
//}



//进程等待
//wait(int* status)演示
//int main(){
//    pid_t ret = fork();
//    if(ret==-1){
//        printf("子进程创建失败");
//    }
//    else if(ret == 0){
//        printf("我是子进程，我的pid是%d，我的父进程ppid是%d，现在我将存活3秒\n",getpid(),getppid());
//        sleep(3);
//        printf("存活结束\n");
//    }
//    else{
//        int status;
//        sleep(4);
//        printf("我是父进程，我的pid为%d，我将会对子进程的僵尸进程进行处理\n",getpid());
//        sleep(1);
//        wait(&status);
//        printf("处理完成\n");
//        sleep(1);
//        printf("子进程是否正常退出：\n");
//        sleep(1);
//        if(WIFEXITED(status)){
//            printf("是\n");
//        }
//        else {
//            printf("否\n");
//        }
//        sleep(1);
//        printf("子进程的正常退出代码为%d\n",WEXITSTATUS(status));
//        sleep(1);
//    }
//    return 0;
//}
//waitpid(pid_t pid,int* status,int options)和非阻塞等待演示

typedef void(*func_t)();
#define NUM 5
func_t funcArr[NUM+1];
void Download(){
    printf("我是一个下载任务\n");
}
void Flush(){
    printf("我是一个刷新任务\n");
}
void Log(){
    printf("我是一个记录日志任务\n");
}



void Registration(func_t h[],func_t f){
    int i = 0;
    for(;i<NUM;i++){
        if(h[i]==NULL) break;
    }
    if(i==NUM)
        return;
    h[i]=f;
    h[i+1]=NULL;
}
int main(){
    Registration(funcArr,Download);
    Registration(funcArr,Flush);
    Registration(funcArr,Log);
    pid_t rid = fork();
    if(rid == -1){
        printf("子进程加载失败，提前退出\n");
        exit(1);
    }
    else if(rid == 0){
        printf("我是子进程，我的进程id为%d，我的父进程为%d，我将会存活10秒\n",getpid(),getppid());
        int cnt = 10;
        while(cnt--){
            sleep(1);
        }
    }
    else{
        sleep(1);
        int status;
        printf("我是父进程，我的id是%d，我将会处理子进程\n",getpid());
        while(1){
            pid_t ret = waitpid(-1,&status,WNOHANG);
            if(ret == -1){
                printf("等待失败,退出\n");
                break;
            }
            else if(ret == 0){
                printf("继续等待，同时进行别的任务\n");
                int i = 0;
                for(;funcArr[i];i++){
                    funcArr[i]();
                }
                printf("本轮任务结束,子进程没有退出\n");
                sleep(1);
            }
            else{
                sleep(1);
                printf("等待成功，已将子进程的僵尸进程回收\n");
                sleep(1);
                break;
            }
        }
    }
    return 0;
}











